package models

import (
	"strings"

	"gitee.com/sansaniot/ssiot-core/httpmvc/model"
	"gorm.io/datatypes"

	cDto "ssdevice/common/dto"
	"ssdevice/common/utils"
	"ssdevice/internal/device/models/query"
)

type SysProductVariable struct {
	ProductModel string          `json:"productModel" gorm:"primaryKey;autoIncrement:false;type:varchar(255);comment:产品编码"`
	Key          string          `json:"key" gorm:"primaryKey;autoIncrement:false;type:varchar(255);comment:变量标识"`
	Label        string          `json:"label" gorm:"type:varchar(255);comment:变量名称"`
	Type         string          `json:"type" gorm:"type:varchar(32);comment:变量类型"`
	Value        string          `json:"value" gorm:"type:text;comment:变量值"`
	Config       datatypes.JSON  `json:"config" gorm:"type:jsonb;comment:变量配置"`
	Param        datatypes.JSON  `json:"param" gorm:"type:jsonb;comment:变量扩展"`
	ReportTime   *cDto.LocalTime `json:"reportTime" gorm:"type:timestamptz(6);comment:变量上报时间"`
	UpdateTime   *cDto.LocalTime `json:"updateTime" gorm:"type:timestamptz(6);comment:变量平台时间"`
	Index        *int            `json:"index" gorm:"type:int2;comment:变量序号"`

	model.Model

	ProductName string `json:"productName" gorm:"-"`
	DeviceType  string `json:"deviceType" gorm:"-"`
	DeptId      string `json:"deptId" gorm:"-"`
	DeptName    string `json:"deptName" gorm:"-"`
}

func (SysProductVariable) TableName() string {
	return "sys_product_variable"
}

func (e *SysProductVariable) Generate() interface{} {
	o := *e
	return &o
}

func (e *SysProductVariable) FindVariableList(req *query.SysProductVariableQuery) (err error, result interface{}) {
	// 处理分组产品model过滤
	var deptIdIn []string
	if len(req.DeptId) == 0 {
		if req.UserId != "1" {
			deptIdIn = req.DeptIdList
		}
	} else {
		deptIdIn = strings.Split(strings.ReplaceAll(req.DeptId, " ", ""), ",")
	}
	productQuery := query.SysProductQuery{DeptIdIn: deptIdIn}
	if len(req.DeptIdNot) > 0 {
		productQuery.DeptIdNIn = strings.Split(strings.ReplaceAll(req.DeptIdNot, " ", ""), ",")
	}
	pdModel := &SysDevProduct{}
	pdModel.Orm = e.Orm
	modelList := make([]string, 0)
	pdList := make([]SysDevProduct, 0)
	modelName := make(map[string]string)
	modelType := make(map[string]string)
	modelDeptId := make(map[string]string)
	if err = pdModel.FindList(&pdList, cDto.MakeCondition(productQuery)); err != nil {
		return
	}
	// 权限处理
	queryModelIn := req.ProductModelIn
	for _, pd := range pdList {
		modelList = append(modelList, pd.ProductModel)
		modelName[pd.ProductModel] = pd.Name
		modelType[pd.ProductModel] = pd.DeviceType
		modelDeptId[pd.ProductModel] = pd.DeptId
	}
	req.ProductModelIn = modelList
	if len(queryModelIn) > 0 {
		// 取交集
		for i := len(req.ProductModelIn) - 1; i >= 0; i-- {
			if !utils.StrIn(req.ProductModelIn[i], queryModelIn) {
				req.ProductModelIn = append(req.ProductModelIn[:i], req.ProductModelIn[i+1:]...)
			}
		}
		if len(req.ProductModelIn) == 0 {
			result = norecord(req.PageIndex, req.PageSize)
			return
		}
	}
	// 查询变量
	list := make([]SysProductVariable, 0)
	var count int64
	if req.PageIndex > 0 && req.PageSize > 0 {
		err = e.FindPage(&list, &count,
			cDto.MakeCondition(req.GetNeedSearch()),
			cDto.OrderDest("product_model,key", true, req.OrderBy),
			cDto.Paginate(req.GetPageSize(), req.GetPageIndex()),
		)
		groupIdName, _ := utils.GroupIdName(e.Orm)
		for i := range list {
			productModel := list[i].ProductModel
			if deptId, ok := modelDeptId[productModel]; ok {
				list[i].DeptId = deptId
				if deptName, ok2 := groupIdName[deptId]; ok2 {
					list[i].DeptName = deptName
				}
			}
			if pdname, ok := modelName[productModel]; ok {
				list[i].ProductName = pdname
			}
			if devtype, ok := modelType[productModel]; ok {
				list[i].DeviceType = devtype
			}
		}
		result = &cDto.Page{
			Records:   list,
			Total:     count,
			PageSize:  req.GetPageSize(),
			PageIndex: req.GetPageIndex(),
			Pages:     (count + int64(req.GetPageSize()) - 1) / int64(req.GetPageSize()),
			Other:     nil,
		}
	} else {
		err = e.FindList(&list,
			cDto.MakeCondition(req.GetNeedSearch()),
			cDto.OrderDest("sn,key", true, req.OrderBy),
		)
		groupIdName, _ := utils.GroupIdName(e.Orm)
		for i := range list {
			productModel := list[i].ProductModel
			if deptId, ok := modelDeptId[productModel]; ok {
				list[i].DeptId = deptId
				if deptName, ok2 := groupIdName[deptId]; ok2 {
					list[i].DeptName = deptName
				}
			}
			if pdname, ok := modelName[productModel]; ok {
				list[i].ProductName = pdname
			}
			if devtype, ok := modelType[productModel]; ok {
				list[i].DeviceType = devtype
			}
		}
		result = list
	}
	return
}

func (e *SysProductVariable) GenFromSchemaProfile(productModel string, devSchema, devConfig map[string]interface{}, varKeyMap map[string]map[string]interface{}) (vars []SysProductVariable) {
	vars = make([]SysProductVariable, 0)
	sensorSchema := utils.GetFieldFromJson([]string{"properties", "sensor", "properties"}, devSchema).(map[string]interface{})
	flattenSensorSchema := map[string]interface{}{}
	utils.FlattenJson(sensorSchema, flattenSensorSchema, []string{})
	profileConfigSensor := utils.GetFieldFromJson([]string{"config", "sensor"}, devConfig)
	// 全量key
	allKeys := make([]string, 0)
	// key-title
	keyTitle := make(map[string]interface{})
	// key-type
	keyType := make(map[string]interface{})
	for k, v := range flattenSensorSchema {
		k = strings.ReplaceAll(k, ".properties.", ".")
		if strings.HasSuffix(k, ".title") {
			k = strings.ReplaceAll(k, ".title", "")
			keyTitle[k] = v
		} else if strings.HasSuffix(k, ".type") {
			k = strings.ReplaceAll(k, ".type", "")
			keyType[k] = v
		}
		if !utils.StrIn(k, allKeys) {
			allKeys = append(allKeys, k)
		}
	}
	// 形成结果
	for _, key := range allKeys {
		tmpVar := SysProductVariable{
			ProductModel: productModel,
			Key:          key,
			Label:        key,
		}
		if title, ok := keyTitle[key]; ok && title != nil {
			tmpVar.Label = title.(string)
		}
		if tp, ok := keyType[key]; ok && tp != nil {
			tmpVar.Type = tp.(string)
		}
		if profileConfigSensor != nil {
			config := utils.GetFieldFromJson(strings.Split(key, "."), profileConfigSensor.(map[string]interface{}))
			if config != nil {
				tmpVar.Config = utils.MapToBytes(config.(map[string]interface{}))
			}
		}
		if varKeyMap != nil {
			if m, ok := varKeyMap[key]; ok && m != nil {
				if index, ok := m["index"]; ok {
					idx := index.(int)
					tmpVar.Index = &idx
				}
				if m["param"] != nil {
					tmpVar.Param = []byte(m["param"].(string))
				}
			}
		}
		if tmpVar.Type != "object" {
			vars = append(vars, tmpVar)
		}
	}
	return
}
